package il.ac.technion.wiki.api.expressions;

import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import il.ac.technion.wiki.api.search.Hit;
import il.ac.technion.wiki.api.search.IndexSearcher;

public class OrOp extends BinaryOperation {

	protected void evaluate(IndexSearcher iSearcher){
		this.fstElement.evaluate(iSearcher);
		this.sndElement.evaluate(iSearcher);
		
		this.hits = zigzagJoin(this.fstElement.hits,this.sndElement.hits,iSearcher);
	}

	private List<Hit> zigzagJoin(List<Hit> hits1,List<Hit> hits2,IndexSearcher iSearcher){
		List<Hit> $ = new LinkedList<Hit>();
		Collections.sort(hits1);
		Collections.sort(hits2);
		Iterator<Hit> iter1= hits1.iterator();
		Iterator<Hit> iter2= hits2.iterator();
		
		Hit h1 = null, h2 = null;
		if (iter1.hasNext()) h1 = iter1.next();
		if (iter2.hasNext()) h2 = iter2.next();
		
		while (h1 != null || h2 != null){
			if (h1 == null){
				$.add(new Hit(iSearcher.orScore(0,h2.getScore()), 
					      h2.getTitle()));
				h2 = null;
				if (iter2.hasNext()) 
					h2 = iter1.next();
				continue;
			}
			if (h2 == null){
				$.add(new Hit(iSearcher.orScore(0,h1.getScore()), 
					      h1.getTitle()));
				h1 = null;
				if (iter2.hasNext()) 
					h2 = iter1.next();
				continue;
			}
			int res = h1.compareTo(h2);
			if (res == 0){
				$.add(new Hit(iSearcher.andScore(h1.getScore(),h2.getScore()), 
						      h1.getTitle()));
				h1=null; h2=null;
				if (iter1.hasNext()) 
					h1 = iter1.next();
				if (iter2.hasNext()) 
					h2 = iter2.next();
			}
			else if (res < 0){
				$.add(new Hit(iSearcher.orScore(h1.getScore(),0), 
					      h1.getTitle()));
				h1=null;
				if (iter1.hasNext()) 
					h1 = iter1.next();
			}
			else {
				$.add(new Hit(iSearcher.orScore(0,h2.getScore()), 
					      h2.getTitle()));
				h2=null;
				if (iter2.hasNext()) 
					h2 = iter2.next();
			}
		}
		return $;
	}
}